package app.goods.info.services;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import app.goods.info.constants.ConstontValue;
import app.goods.info.constants.GlobalCache;
import app.goods.info.constants.UrlConstont;
import app.goods.info.services.domain.CataLogue;
import app.goods.info.services.domain.GoodsInfo;
import app.goods.info.services.domain.ShopInfo;
import app.goods.info.utils.FileReaderUtils;
import app.goods.info.utils.HttpClientUtils;
import app.goods.info.utils.PropertiesUtils;
import app.goods.info.utils.UrlUtils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;

public class CentralizedProcurementGoodsServie {
	private static final Logger LOGGER = LoggerFactory.getLogger(CentralizedProcurementGoodsServie.class);

	public List<GoodsInfo> getAllCentralizedGoods() {
		// 创建一个固定大小的线程池
		ExecutorService executor = Executors.newFixedThreadPool(9);
		List<Future<List<GoodsInfo>>> futures = new ArrayList<>();
		List<CataLogue> catalogues = GlobalCache.getInstance().getTargetCataLogues();
		List<GoodsInfo> result = new ArrayList<GoodsInfo>();
		catalogues.forEach(catalogue -> {
			Future<List<GoodsInfo>> future = executor.submit(new GetGoodsFuture(catalogue));
			futures.add(future);
		});
		// 等待所有任务完成
		for (Future<List<GoodsInfo>> future : futures) {

			try {
				result.addAll(future.get());
			} catch (InterruptedException | ExecutionException e) {
				LOGGER.error(e.getMessage(), e);
			} // 阻塞，直到任务完成并返回结果
			LOGGER.info("All task are done!!!");

		}

		// 关闭线程池
		executor.shutdown();
		// FileReaderUtils.writeAllGoodsIntoOneExcel(result);
		GlobalCache.getInstance().setAllGoodsInfos(result);
		return result;
	}

	public List<GoodsInfo> getCentralizedGoodsByCatalogueNoWithShopNo(CataLogue cataLogue) {
		LOGGER.info("Catalogue no: {} start", cataLogue.getCatalogueNo());
		List<ShopInfo> targetShopInfos = GlobalCache.getInstance().getAllShopInfos().stream()
				.filter(shopInfo -> shopInfo.getStatus().equals("ON")).collect(Collectors.toList());

		final List<GoodsInfo> result = new ArrayList<GoodsInfo>();
		targetShopInfos.forEach(shopInfo -> {
			int pageNum = 1;
			result.addAll(getCentralizedGoodsByPageWithShopNo(cataLogue.getCatalogueNo(), shopInfo, pageNum));
		});
		List<GoodsInfo> resultFinal = getFiltedShopGoods(result);
		LOGGER.info("Catalogue no: {} done total : {}", cataLogue.getCatalogueNo(), resultFinal.size());
//		FileReaderUtils.writeCatalogueGoodsIntoOneExcel(result, cataLogue.getCatalogueName());
//		FileReaderUtils.writeAllCatalogueGoodsIntoOneExcel(result, cataLogue.getCatalogueName());
		FileReaderUtils.writeAllGoodsIntoOneExcelPageByCatalogue(cataLogue.getCatalogueName(), resultFinal);
		GlobalCache.getInstance().getCatalogueGoodsInfos().put(cataLogue.getCatalogueName(), resultFinal);
		String filePath = "data" + File.separator +  cataLogue.getCatalogueNo() + ".json";
		LOGGER.info("data===" + filePath);
		FileReaderUtils.writeJsonToFileByLine(JSONUtil.toJsonStr(resultFinal),filePath);
		return resultFinal;
	}

	public List<GoodsInfo> getCentralizedGoodsByPageWithShopNo(String catalogueNo, ShopInfo shopInfo, int pageNum) {
		LOGGER.info("Shop no:{}, Catalogue no: {} page number:{}",shopInfo.getShopNo(), catalogueNo, pageNum);
		List<GoodsInfo> result = new ArrayList<GoodsInfo>();
		String queryUrl = UrlConstont.CENTRALIZED_PROCUREMENT_GOODS_SHOP.concat(pageNum + "?");
		queryUrl = UrlUtils.getRequestUrl(queryUrl);
		queryUrl = queryUrl.concat("catalogue_no=").concat(catalogueNo).concat("&shop_no=").concat(shopInfo.getShopNo())
				.concat("&search_mode=1&sort_type=10&coordinate=").concat(String.valueOf(shopInfo.getLatitude()))
				.concat(",").concat(String.valueOf(shopInfo.getLongitude()));
		String responseBody = HttpClientUtils.get(queryUrl, UrlUtils.builQueryParameters());
		if (StringUtils.isNotEmpty(responseBody)) {
			String messageCode = JSONUtil.parseObj(responseBody).getStr("code");
			if ("0".equals(messageCode)) {
				JSONArray allGoodsArray = JSONUtil.parseObj(responseBody).getJSONObject("result").getJSONArray("list");
				if (allGoodsArray != null && allGoodsArray.size() > 0) {
					result.addAll(JSONUtil.toList(allGoodsArray, GoodsInfo.class));
					try {
						Integer waitTimeConf = Integer.valueOf(
								PropertiesUtils.getValueByKeyFromResources(ConstontValue.CONFIG_FILE_NAME, "waitTime"));
						Thread.sleep(waitTimeConf);
					} catch (InterruptedException e) {
						LOGGER.error(e.getMessage(), e);
					}
					// result.addAll(getCentralizedGoodsByPageWithShopNo(catalogueNo, shopNo,
					// pageNum + 1));
				}
			}
		} else {
			Optional<CataLogue> errCataLogue = GlobalCache.getInstance().getTargetCataLogues().stream()
					.filter(cata -> cata.getCatalogueNo().equals(catalogueNo)).findFirst();
			GlobalCache.getInstance().getErrorCataLogue().add(errCataLogue.get());
			System.err.println(JSONUtil.toJsonPrettyStr(
					GlobalCache.getInstance().getErrorCataLogue().stream().map(CataLogue::getCatalogueName)));
		}

		return result;
	}

	public List<GoodsInfo> getCentralizedGoodsByCatalogueNo(CataLogue cataLogue) {
		LOGGER.info("Catalogue no: {} start", cataLogue.getCatalogueNo());
		int pageNum = 1;
		List<GoodsInfo> result = getCentralizedGoodsByPage(cataLogue.getCatalogueNo(), pageNum);
		result = getFiltedShopGoods(result);
		LOGGER.info("Catalogue no: {} done total : {}", cataLogue.getCatalogueNo(), result.size());
//		FileReaderUtils.writeCatalogueGoodsIntoOneExcel(result, cataLogue.getCatalogueName());
//		FileReaderUtils.writeAllCatalogueGoodsIntoOneExcel(result, cataLogue.getCatalogueName());
		FileReaderUtils.writeAllGoodsIntoOneExcelPageByCatalogue(cataLogue.getCatalogueName(), result);
		GlobalCache.getInstance().getCatalogueGoodsInfos().put(cataLogue.getCatalogueName(), result);
		FileReaderUtils.writeJsonToFileByLine(JSONUtil.toJsonPrettyStr(result),
				"/data/" + cataLogue.getCatalogueNo() + ".json");
		return result;
	}

	public List<GoodsInfo> getCentralizedGoodsByPage(String catalogueNo, int pageNum) {
		LOGGER.info("Catalogue no: {} page number:{}", catalogueNo, pageNum);
		List<GoodsInfo> result = new ArrayList<GoodsInfo>();
		String queryUrl = UrlConstont.CENTRALIZED_PROCUREMENT_GOODS.concat(pageNum + "?");
		queryUrl = UrlUtils.getRequestUrl(queryUrl);
		queryUrl = queryUrl.concat("catalogue_no=").concat(catalogueNo)
				.concat("&search_mode=1&sort_type=10&coordinate=33.988217%2C118.209162");
		String responseBody = HttpClientUtils.get(queryUrl, UrlUtils.builQueryParameters());
		if (StringUtils.isNotEmpty(responseBody)) {
			String messageCode = JSONUtil.parseObj(responseBody).getStr("code");
			JSONArray allGoodsArray = JSONUtil.parseObj(responseBody).getJSONObject("result").getJSONArray("list");
			// 开发调试
//			 if (allGoodsArray != null && allGoodsArray.size() > 0 && pageNum < 2) {
			if (allGoodsArray != null && allGoodsArray.size() > 0) {
				result.addAll(JSONUtil.toList(allGoodsArray, GoodsInfo.class));
				try {
					Integer waitTimeConf = Integer.valueOf(
							PropertiesUtils.getValueByKeyFromResources(ConstontValue.CONFIG_FILE_NAME, "waitTime"));
					Thread.sleep(waitTimeConf);
				} catch (InterruptedException e) {
					LOGGER.error(e.getMessage(), e);
				}
				result.addAll(getCentralizedGoodsByPage(catalogueNo, pageNum + 1));
			}
		}
		return result;
	}

	public List<GoodsInfo> getFiltedShopGoods(List<GoodsInfo> goodsInfos) {
		return goodsInfos.stream().filter(shopGoodsInfo -> isTargetShopName(shopGoodsInfo.getShopName()))
				.collect(Collectors.toList());
	}

	private boolean isTargetShopName(String shopName) {
		List<ShopInfo> targetShopInfos = GlobalCache.getInstance().getAllShopInfos().stream()
				.filter(shopInfo -> shopInfo.getStatus().equals("ON")).collect(Collectors.toList());

		return targetShopInfos.stream().anyMatch(targetShopName -> targetShopName.getShopName().equals(shopName));
	}

	public List<GoodsInfo> getCentralizedGoodsByCatalogueNo1(CataLogue cataLogue) {
		LOGGER.info("Catalogue no: {} start", cataLogue.getCatalogueNo());
		int pageNum = 1;
		List<GoodsInfo> result = getCentralizedGoodsByPage1(cataLogue.getCatalogueNo(), pageNum);
		result = getFiltedShopGoods(result);
		LOGGER.info("Catalogue no: {} done total :{} ", cataLogue.getCatalogueNo(), result.size());
//		FileReaderUtils.writeCatalogueGoodsIntoOneExcel(result, cataLogue.getCatalogueName());
//		FileReaderUtils.writeAllCatalogueGoodsIntoOneExcel(result, cataLogue.getCatalogueName());
		FileReaderUtils.writeAllGoodsIntoOneExcelPageByCatalogue(cataLogue.getCatalogueName(), result);
		GlobalCache.getInstance().getCatalogueGoodsInfos().put(cataLogue.getCatalogueName(), result);
		FileReaderUtils.writeJsonToFileByLine(JSONUtil.toJsonPrettyStr(result),
				"/data/" + cataLogue.getCatalogueNo() + ".json");
		Map<String, List<GoodsInfo>> groupedByShopName = result.stream()
				.collect(Collectors.groupingBy(GoodsInfo::getShopName));
		System.err.println("end......" + result.size() + " shop size:" + groupedByShopName.size());
		return result;
	}

	public List<GoodsInfo> getCentralizedGoodsByPage1(String catalogueNo, int pageNum) {
		LOGGER.info("Catalogue no: {} page number:{}", catalogueNo, pageNum);
		List<GoodsInfo> result = new ArrayList<GoodsInfo>();
		String queryUrl = UrlConstont.CENTRALIZED_PROCUREMENT_GOODS.concat(pageNum + "?");
		queryUrl = UrlUtils.getRequestUrl(queryUrl);
		queryUrl = queryUrl.concat("catalogue_no=").concat(catalogueNo)
				.concat("&search_mode=1&sort_type=10&coordinate=33.988217%2C118.209162");
		String responseBody = HttpClientUtils.get(queryUrl, UrlUtils.builQueryParameters());
		if (StringUtils.isNotEmpty(responseBody)) {
			String messageCode = JSONUtil.parseObj(responseBody).getStr("code");
			JSONArray allGoodsArray = JSONUtil.parseObj(responseBody).getJSONObject("result").getJSONArray("list");
			if (allGoodsArray != null && allGoodsArray.size() > 0) {
				result.addAll(JSONUtil.toList(allGoodsArray, GoodsInfo.class));
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					LOGGER.error(e.getMessage(), e);
				}
				result.addAll(getCentralizedGoodsByPage1(catalogueNo, pageNum + 1));
			}
		}
		return result;
	}

	public static void main(String[] args) {
		String token = "84480E7CB22636E1388E96B9BA36FB89";
		GlobalCache.getInstance().initAllCache();
		GlobalCache.getInstance().setLoginToken(token);
		long now = System.currentTimeMillis();
		CentralizedProcurementGoodsServie centralizedProcurementGoodsServie = new CentralizedProcurementGoodsServie();
//		List<GoodsInfo> result = centralizedProcurementGoodsServie.getAllCentralizedGoods();
		CataLogue cataLogue = new CataLogue();
		cataLogue.setCatalogueName("蔬菜（集采）");
		cataLogue.setCatalogueNo("2200");
		List<GoodsInfo> result = centralizedProcurementGoodsServie.getCentralizedGoodsByCatalogueNo(cataLogue);
		FileReaderUtils.writeAllGoodsIntoOneExcel(result);
		System.out.println("All tasks done, spent time " + ((System.currentTimeMillis() - now) / 1000) + "秒");
	}
}
